home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 June: Reference Library / Dev.CD Jun 94.toast / Periodicals / develop / develop Issue 14 / develop 14 code / Writing Localizable Apps / Poor Man's Unification.c < prev   
Encoding:
Text File  |  1993-03-09  |  4.3 KB  |  168 lines  |  [TEXT/KAHL]

  1. /**********************************************************************************
  2.  
  3.     NOTE: This file won't compile as-is, though each sample has been compiled on its
  4.     own. The code here has been extracted from the article simply for your convenience, 
  5.     so you won't have to type it in. Take what you need, and adapt it for your own 
  6.     devious purposes.
  7.     
  8. ***********************************************************************************/
  9.  
  10.  
  11. //--------------------------------------
  12. //    Changing fonts when using "poor man's 
  13. //    unification"
  14.  
  15. #define asciiSegment    0
  16. #define    europeanSegment    1
  17. #define    katakanaSegment    2
  18. #define    japaneseSegment    3
  19.  
  20. short fontScript, runSegment, runScript;
  21. short textRunIndex, textRunCount;
  22.  
  23. fontScript = Font2Script(myNewFontID);
  24. for (textRunIndex = 0;
  25.         textRunIndex < textRunCount;
  26.         textRunIndex++) {
  27.     runSegment = textRunStore[textRunIndex].segment;
  28.     runScript = textRunStore[textRunIndex].script;
  29.     if (SegmentAllowedInScript(runSegment, runScript))
  30.         textRunStore[textRunIndex].fontID = myNewFontID;
  31. }
  32.  
  33. Boolean SegmentAllowedInScript(short segment, short script)
  34. {
  35.     switch (script) {
  36.         case smRoman:
  37.             switch (segment) {
  38.                 case asciiSegment:
  39.                 case europeanSegment:
  40.                     return true;
  41.                 default:
  42.                     return false;
  43.             }
  44.         case smJapanese:
  45.             switch (segment) {
  46.                 case asciiSegment:
  47.                 case katakanaSegment:
  48.                 case japaneseSegment:
  49.                     return true;
  50.                 default:
  51.                     return false;
  52.             }
  53.         default:
  54.             switch (segment) {
  55.                 case asciiSegment:
  56.                     return true;
  57.                 default:
  58.                     return false;
  59.             }
  60.     }
  61. }
  62.  
  63. //--------------------------------------
  64. //    Determining the segment from the keyboard 
  65. //    input for "poor man's unification"
  66.  
  67. #define ksJISSpace    0x8140
  68.  
  69. unsigned short keyboardScript;
  70. unsigned short charSegment;
  71. EventRecord     lowByteEvent;
  72.  
  73. keyboardScript = GetEnvirons(smKeyScript);
  74. charSegment = ScriptAndByteToSegment(keyboardScript, charCode);
  75. if (charSegment == japaneseSegment) {
  76.     // Get low byte of two-byte character from keyboard.
  77.     do {
  78.         // You can get null events between two bytes of a two-byte
  79.         // character.
  80.         GetNextEvent(keyDownMask | keyUpMask | autoKeyMask,
  81.             &lowByteEvent);
  82.         if (lowByteEvent.what == nullEvent)
  83.             GetNextEvent(keyDownMask | keyUpMask | autoKeyMask,
  84.                 &lowByteEvent);
  85.     } while (lowByteEvent.what == keyUp);
  86.  
  87.     if ((lowByteEvent.what == keyDown) ||
  88.             (lowByteEvent.what == autoKey))
  89.         charCode = (charCode << 8) | 
  90.             (lowByteEvent.message & charCodeMask);
  91.     else
  92.         // We've gotten a valid high byte under the Japanese keyboard
  93.         // with no subsequent low byte forthcoming. Something serious is
  94.         // wrong with the current input method. Return a Japanese space
  95.         // for now. Hmmmm.
  96.         charCode = ksJISSpace;
  97. }
  98.  
  99.  
  100. #define kASCIILow    0x00
  101. #define kASCIIHigh    0x7f
  102. #define kRange1Low    0x81
  103. #define kRange1High    0x9f
  104. #define kRange2Low    0xe0
  105. #define kRange2High    0xfc 
  106.  
  107. short ScriptAndByteToSegment(unsigned short script,
  108.     unsigned char byte)
  109. {
  110.     switch (script) {
  111.         case smRoman:
  112.             if ((byte >= kASCIILow) && (byte <= kASCIIHigh)) 
  113.                 return asciiSegment;
  114.             else 
  115.                 return europeanSegment;
  116.         case smJapanese:
  117.             if ((byte >= kASCIILow) && (byte <= kASCIIHigh)) 
  118.                 return asciiSegment;
  119.             else if ((byte >= kRange1Low) && (byte <= kRange1High)) 
  120.                 return japaneseSegment;
  121.             else if ((byte >= kRange2Low) && (byte <= kRange2High)) 
  122.                 return japaneseSegment;
  123.             else 
  124.                 return katakanaSegment;
  125.         default:
  126.             // New scripts and segments added before this.
  127.             return asciiSegment;
  128.     }
  129. }
  130.  
  131. //--------------------------------------
  132. //    "Smart" font forcing for Poor man's 
  133. //    unification.
  134.  
  135. short fontScript, keyboardScript;
  136.  
  137. fontScript = Font2Script(myFontID);
  138. keyboardScript = GetEnvirons(smKeyScript);
  139. // Search backward.
  140. if (fontScript != keyboardScript) {
  141.     for (textRunIndex = currentRunIndex - 1;
  142.             textRunIndex >= 0;
  143.             textRunIndex--) {
  144.         myFontID = textRunStore[textRunIndex].fontID;
  145.         fontScript = Font2Script(myFontID);
  146.         if (fontScript == keyboardScript)
  147.             break;
  148.     }
  149. }
  150.  
  151. // Search forward.
  152. if (fontScript != keyboardScript) {
  153.     for (textRunIndex = currentRunIndex + 1;
  154.             textRunIndex < textRunCount;
  155.             textRunIndex++) {
  156.         myFontID = textRunStore[textRunIndex].fontID;
  157.         fontScript = Font2Script(myFontID);
  158.         if (fontScript == keyboardScript)
  159.             break;
  160.     }
  161. }
  162.  
  163. // Punt if we couldn't find an appropriate run.
  164. if (fontScript != keyboardScript)
  165.     myFontID = GetScript(keyboardScript, smScriptAppFond);
  166.  
  167.  
  168. }